'use strict';

// eslint-disable-next-line no-unused-vars
const Service = require('egg').Service;
const BaseService = require('./base');
const { Op } = require('sequelize');
const moment = require("moment");

class UserService extends BaseService {

  async findUserInfo(ids) {
    return await this.ctx.model.User.findAll({
      where: {
        id: {
          [Op.in]: ids
        }
      },
      attributes: ["id", 'nickname', "avatar"]
    })
  }

  
  /**
   * 话题被赞用户
   */
  async getThemeUser(ids, page = 0, size = 15) {
    const { rows, count } = await this.ctx.model.User.findAndCountAll({
      where: {
        id: {
          [Op.in]: ids
        }
      },
      offset: page * size,
      limit: size,
    })
    return {item: rows, totalCount: count};
  }

  async findBySex(sex) {
    const user = await this.ctx.model.User.findAll({
      where: {
        sex
      },
      attributes: ['id']
    });
    let userId = [];
    if (user) {
      user.forEach(u => {
        userId.push(u.dataValues.id);
      })
    }
    return userId;
  }

  async getRecommendUser(user, where, like) {
    let users = await this.findRecommendUser(user, where, like);
    if (!users) {
      return [];
    }
    
    for (let i = 0; i < users.length; i++) {
      const images = await this.service.userImage.findByUserId(users[i].id);
      let arr = [];
      if (images) {
          images.forEach(i => {
            arr.push(i.dataValues);
          })
      }
      users[i].images = arr;    
    }
    return users;
  }

  async findRecommendUser(user, where, like) {
    // HAVING
    //    distance <= 100000
    try {
        return await this.app.model.query(`
      SELECT
        u.*,
        ROUND(
          6378.138 * 2 * ASIN(
            SQRT(
              POW( SIN( ( ${user.latitude} * PI() / 180 - latitude * PI( ) / 180 ) / 2 ), 2 ) + COS(${user.latitude} * PI() / 180 ) * COS( latitude * PI( ) / 180 ) * POW( SIN( ( ${user.longitude} * PI( ) / 180- longitude * PI( ) / 180 ) / 2 ), 2 ) 
            ) 
          ) * 1000 
        ) AS distance
      FROM
        user as u
      WHERE 
        sex in (${where.sex})
      AND   
        age >= ${where.minAge}
      AND 
        age <= ${where.maxAge}
      AND
        height >= ${where.minHeight}
      AND
        height <= ${where.maxHeight}
      AND 
        education_level in (${where.educationLevel})
      AND 
        constellation in ("${where.constellation}")
      AND
        u.id != ${user.id}
      AND
        u.id not in (${like})
      ORDER BY
        distance ASC
      LIMIT 21
      `, {
        type: 'SELECT'
      });
    } catch (e) {
      return e;
    }
    
  }

  async update(id, data) {
    const user = await this.ctx.model.User.findByPk(id);
    if (!user) {
      this.ctx.helper.commonErr('用户不存在');
    } 
    const transaction = await this.ctx.model.transaction();
    try {
      user.update(data);
      this.updateCompletion(user);
      await transaction.commit();
    } catch(e) {
      await transaction.rollback();
    }
  }

  /**
   * 计算完成度
   * 图片6，回答3，日常3，愿望3
   * 学校，公司，职业，目的，昵称，性别，身高，生日，家乡，位置各1
   * 每个4%，共25
   */
   async updateCompletion(user) {
    const image = await this.service.userImage.findByUserId(user.id);
    const answer = await this.service.userQuestion.query(user.id);
    const daily = user.daily.split("|~|~");
    const wish = user.wish.split("|~|~");
    const school = user.school ? 1 : 0;
    const company = user.company ? 1 : 0;
    const profession = user.profession ? 1 : 0;
    const purpose = user.purpose ? 1 : 0;
    const nickname = user.nickname ? 1 : 0;
    const sex = user.sex ? 1 : 0;
    const height = user.height ? 1 : 0;
    const birthday = user.birthday ? 1 : 0;
    const city = user.city ? 1 : 0;
    const longitude = user.longitude ? 1 : 0;
    const completion = (image.length + answer.length, daily.length + wish.length + school + company
       + profession + purpose + nickname + sex + height + birthday + city + longitude) * 4;
       console.log(completion);
    user.finish = completion;
    user.save();
  }

  /**
   *  剩余VIP天数
   */
  async getLastVipDays(userId) {
    const user = await this.ctx.model.User.findByPk(userId);
    const now = moment().format("YYYY-MM-DD");
    let days = 0;
    if (moment(user.expire_time) > moment(now)) {
      days = moment(user.expire_time).diff(moment(now), "days");
    }
    return days;
  }


  async findByWxappOpenid(openid) {
    return await this.ctx.model.User.findOne({
      where: { 
        wxapp_openid: openid
      },
      attributes: ['id', 'wxapp_openid', 'phone']
    })
  }

  async bindUser(data) {
    let user = await this.findByPhone(data.phone);
    const transaction = await this.ctx.model.transaction();
    try {
      if (!user) {
        user  = await this.add({
          wxapp_openid: data.openid,
          phone: data.phone,
        })
        //邀请好友
        if ("userId" in data) {
          const friend = await this.ctx.model.User.findByPk(data.userId);
          if (!friend) {
            this.commonErr("分享用户不存在");
          }
          //添加好友
          this.service.inviteFriend.add(friend.id, user.id);
          //更新用户
          this.updateByInviteUser(friend);
        }
        
      }
      
      await transaction.commit();
    } catch (e) {
      console.log(e);
      await transaction.rollback();
    }
    
    return user;
  }

  async updateByInviteUser(user) {
    user.get_like += 1;
    user.use_like += 1;
    user.success_invite += 1;
    //每邀请3个可以获得10天VIP
    if ( user.success_invite >= 3 ) {
      user = await this.getVipTime(user);
      user.success_invite = 0;
      this.service.inviteFriend.updateUnlock(user.id)
    }
    user.save();
  }

  async getVipTime(user, day = 10) {
    const now = moment().format("YYYY-MM-DD")
    const expireTime = moment().add(day, "day").format("YYYY-MM-DD");
    if (user.vip) {
      //vip已过期
      if (moment(user.expire_time) < moment(now)) {
        console.log(expireTime);
          user.open_time = now;
          user.expire_time = expireTime;
      } else {
        user.expire_time = moment(user.expire_time).add(day, "day").format("YYYY-MM-DD");
      }
    } else {
      user.vip = true;
      user.open_time = now;
      user.expire_time = expireTime;
    }
    user.vip_like = 1;
    return user;
  }

  async findByPhone(phone) {
    return await this.ctx.model.User.findOne({
      where: { 
        phone: phone
      },
      attributes: ['id', 'phone', 'wxapp_openid']
    })
  }

  async add(params) {
    return this.run(async () => {
      const { ctx } = this;
      const result = await ctx.model.User.create(params);
      return result;
    });
  }

}

module.exports = UserService;
